package com.ds.app.database;

import com.ds.app.AppCacheManager;
import com.ds.app.ModuleNotFoundException;
import com.ds.common.JDSException;
import com.ds.common.cache.CacheSizes;
import com.ds.common.cache.Cacheable;
import com.ds.common.database.DBAgent;
import com.ds.common.database.DBBeanBase;
import com.ds.common.logging.Log;
import com.ds.common.logging.LogFactory;
import com.ds.org.Person;
import com.ds.org.PersonNotFoundException;
import com.ds.org.conf.OrgConfig;
import com.ds.org.conf.OrgConstants;
import com.ds.org.conf.Query;
import com.ds.org.conf.Query.ColumnMapping;
import com.ds.org.conf.Query.SqlClause;
import com.ds.server.OrgManagerFactory;
import com.ds.server.eumus.ConfigCode;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;


public class DbPersonModuleProperty implements Cacheable, Serializable {

	protected static Log log =
		LogFactory.getLog(OrgConstants.CONFIG_KEY.getType(),
				DbPersonModuleProperty.class);
	public static final String DELETE="DELETE",UPDATE="UPDATE",NORMAL="NORMAL",PUBLIC="public";
	private String status=NORMAL ;
	private String ID;
	private String path;
	private Integer index=0;
	private String moduleId;
	private String personId;
	private String name;
	private String type;
	
	public String icon;//图标地址
	
	public String thumb;//略缩图地址
	
	
	private Integer moduleStatus=0;
	private String childModule;
	private String url;
	private String winConfig;
	private Date creatTime;
	private Date lastModified;

	private String exprocession;
	private ConfigCode configCode;
	private String cls;
	
	private List<DbPersonModuleProperty> childModuleList;
	private boolean isPublic=false;

	 private OrgConfig getConfig(){
		 OrgConfig	config=OrgConfig.getInstance(this.configCode);
			return config;
		}

	public DbPersonModuleProperty(ConfigCode configCode) {
		this.configCode=configCode;
		
	}

	public DbPersonModuleProperty(String moduleId,ConfigCode configCode,String personId) throws ModuleNotFoundException {
		if (moduleId == null || moduleId.equals("")) {
			throw new ModuleNotFoundException();
		}
		this.moduleId=moduleId;
		
		if (personId==null){
			personId=PUBLIC;
		}
		this.personId=personId;
		this.isPublic=true;
		if (configCode==null){
			configCode=OrgConstants.CONFIG_KEY;
		}
		
		this.configCode=configCode;
		loadFromDb();
	}
	public DbPersonModuleProperty(String ID,ConfigCode configCode) throws ModuleNotFoundException {
		if (ID == null || ID.equals("")) {
			throw new ModuleNotFoundException();
		}
		this.ID=ID;
		if (configCode==null){
			configCode=OrgConstants.CONFIG_KEY;
		}
		
		this.configCode=configCode;
		loadFromDb();
	}
	private void loadFromDb() throws ModuleNotFoundException {
		DBAgent db = null;
		try {
			db = new DBAgent(this.configCode.getType());

			loadBasic(db);
		} catch (Exception e) {
			throw new ModuleNotFoundException("ModuleProperty " +name + " not found.");
		} finally {
			if (db!=null){
				db.close();
			}
		}
		
	}
	
	public void update(){

		Person person=null;
		try {

			 person=OrgManagerFactory.getOrgManager().getPersonByID(this.personId);

		} catch (PersonNotFoundException e) {
			e.printStackTrace();
		}	
		
		AppCacheManager.getInstance(configCode).getModulePrivateProcertyCache().put(ID, this);
		//person.addModuleProperty(this.ID);
		this.status=UPDATE;
	}
	
	
	public void commit(Connection c) throws PersonNotFoundException{
		if (status.equals(NORMAL)){
			return;
		}
		Connection innerc=null;
		if (c==null){
			DBBeanBase	db = new DBBeanBase(this.configCode.getType());
			innerc= db.getConn();
		}else{
			innerc=c;
		}
	
		
//		if (!person.getModulePropertyIdList().contains(this.ID)){
//			person.getModulePropertyIdList().add(this.ID);
//		}
		
		try{	
			innerc.setAutoCommit(false);
			this.deleteModuleProperty(innerc);
            if (!status.equals(DELETE)){
            	this.insertModuleProperty(innerc);
			}
            if (c==null){
            	 innerc.commit();
            	 innerc.close();
            }
           	
			this.status=this.NORMAL;
		}catch(SQLException e){
			e.printStackTrace();
			try {
				innerc.rollback();
				innerc.close();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
	}
	
	
	private void loadBasic(DBAgent db) throws Exception{
		
		ResultSet rs = null;
		Query query = null;
		SqlClause sqlClause = null;
		Map columnMap = null;
		String strSql = null;
		
//		 1.基本信息
		query = getConfig().getQuery("PersonModuleProperty");
		if (query == null) {
			log.error("The ModuleProperty-query-sql is null, please specify it!");
			throw new ModuleNotFoundException();
		}
		sqlClause = query.getSqlClause("basic");
		if (sqlClause == null) {
			log.error("The ModuleProperty-query-sql is null, please specify it!");
			throw new ModuleNotFoundException();
		}
		columnMap = sqlClause.getColumnMappings();
		if (this.isPublic){
			strSql = this.buildModuleIdSql(sqlClause);
		}else{
			strSql = buildSql(sqlClause);
		}
		
		
		if (db.execute(strSql) == 1) {
			rs = db.getQueryResult();
			if (!rs.next()) {
				throw new ModuleNotFoundException("PersonModuleProperty " + ID + " not found.");
			}
			 name =
					getString(rs, columnMap.get("name"));
			 ID =
				getString(rs, columnMap.get("ID"));
			 path =
					getString(rs, columnMap.get("path"));
			 index =
					getInt(rs, columnMap.get("index"));
			 moduleStatus =
					getInt(rs, columnMap.get("moduleStatus"));
			 moduleId =
				getString(rs, columnMap.get("moduleId"));
			 personId =
				getString(rs, columnMap.get("personId"));
			 exprocession =
				 getString(rs, columnMap.get("exprocession"));
			 type =
				 getString(rs, columnMap.get("type"));
			 winConfig =
				 getString(rs, columnMap.get("winConfig"));
			 url =
				 getString(rs, columnMap.get("url"));
			 childModule =
				 getString(rs, columnMap.get("childModule"));
			 cls =
				 getString(rs, columnMap.get("cls"));
			 icon =
				 getString(rs, columnMap.get("icon"));
			 thumb= 
				 getString(rs, columnMap.get("thumb"));
			 creatTime= 
				 getDate(rs, columnMap.get("creatTime"));
			 lastModified= 
				 getDate(rs, columnMap.get("lastModified"));
		} else {
			throw new ModuleNotFoundException("PersonModuleProperty " + ID + " not found.");
		}
	}
  
	public int getCachedSize() {
		int size = 0;
		size += CacheSizes.sizeOfString(name);
		size += CacheSizes.sizeOfString(ID);
		size += CacheSizes.sizeOfString(path);
		size += CacheSizes.sizeOfObject(index);
		size += CacheSizes.sizeOfObject(moduleStatus);
		size += CacheSizes.sizeOfString(moduleId);
		size += CacheSizes.sizeOfString(personId);
		size += CacheSizes.sizeOfObject(this.exprocession);
		size += CacheSizes.sizeOfObject(this.type);
		size += CacheSizes.sizeOfObject(this.winConfig);
	    size += CacheSizes.sizeOfObject(this.url);
	    size += CacheSizes.sizeOfObject(this.childModule);
	    size += CacheSizes.sizeOfObject(this.cls);
	    size += CacheSizes.sizeOfObject(this.icon);
	    size += CacheSizes.sizeOfObject(this.thumb);
	    size += CacheSizes.sizeOfObject(this.creatTime);
	    size += CacheSizes.sizeOfObject(this.lastModified);
		return size;
	}


	public String getModuleId() {
		return moduleId;
	}

	public void setModuleId(String moduleId) {
		this.moduleId = moduleId;
	}

	public String getPersonId() {
		return personId;
	}

	public void setPersonId(String personId) {
		this.personId = personId;
	}




	private String buildSql(SqlClause sqlClause) {
			Map columnMap = sqlClause.getColumnMappings();
			String strSql = sqlClause.getMainClause();
			String strWhere = sqlClause.getWhereClause();
			if (strWhere != null && !strWhere.equals("")) {
				strSql = strSql + " " + strWhere + " AND "
						+ ((ColumnMapping) columnMap.get("ID")).getColumn()
						+ "='" + ID + "'";
			} else {
				strSql = strSql + " WHERE "
						+ ((ColumnMapping) columnMap.get("ID")).getColumn()
						+ "='" + ID + "'";
			}
			return strSql;
		}
	private String buildModuleIdSql(SqlClause sqlClause) {
		Map columnMap = sqlClause.getColumnMappings();
		String strSql = sqlClause.getMainClause();
		String strWhere = sqlClause.getWhereClause();
		if (strWhere != null && !strWhere.equals("")) {
			strSql = strSql + " " + strWhere + " AND "
					+ ((ColumnMapping) columnMap.get("moduleId")).getColumn()
					+ "='" + moduleId + "' AND "+columnMap.get("personId")+"='"+this.personId+"'";
		} else {
			strSql = strSql + " WHERE "
					+ ((ColumnMapping) columnMap.get("moduleId")).getColumn()
					+ "='" + moduleId + "' AND "+columnMap.get("personId")+"='"+this.personId+"'";
		}
		return strSql;
	}

	public String getID() {
		return ID;
	}

	public void setID(String id) {
		ID = id;
	}
	
	public void deleteModuleProperty(Connection c) throws SQLException {
		Query query = getConfig().getQuery("PersonModuleProperty");
		SqlClause  sqlClause = query.getSqlClause("basic");
		Map columnMap = sqlClause.getColumnMappings();
		PreparedStatement ps = null;
		StringBuffer _sql=new StringBuffer(sqlClause.getDeleteClause()+" where ");
		_sql.append(columnMap.get("ID")).append("='"+this.ID+"'");
		ps = c.prepareStatement(_sql.toString());
		int deletCount=ps.executeUpdate();
		ps.close();
		
		
		AppCacheManager.getInstance(configCode) .getModulePrivateProcertyCache().remove(ID);
   }
	
    public void insertModuleProperty(Connection c) throws SQLException {
    		Query query = getConfig().getQuery("PersonModuleProperty");
    		SqlClause  sqlClause = query.getSqlClause("basic");
    		Map columnMap = sqlClause.getColumnMappings();
    		StringBuffer _sql=new StringBuffer(sqlClause.getInsertClause()+"(");
    		int _dirtyCount = 0;
    		
        		_sql.append(columnMap.get("ID")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("path")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("index")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("moduleStatus")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("name")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("moduleId")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("personId")).append(",");
    				
    			_dirtyCount++;
    			_sql.append(columnMap.get("exprocession")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("type")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("winConfig")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("url")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("childModule")).append(",");
    			_dirtyCount++;
    		
    			_sql.append(columnMap.get("cls")).append(",");
    			_dirtyCount++;
    			
    			_sql.append(columnMap.get("icon")).append(",");
    			_dirtyCount++;
    		
    			_sql.append(columnMap.get("thumb")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("creatTime")).append(",");
    			_dirtyCount++;
    			_sql.append(columnMap.get("lastModified")).append(",");
    			_dirtyCount++;
     		_sql.setLength(_sql.length() - 1);
    		_sql.append(") values (");
    		for (int i = 0; i < _dirtyCount; i++)
    			_sql.append("?,");
    		_sql.setLength(_sql.length() - 1);
    		_sql.append(")");
      		PreparedStatement ps  = c.prepareStatement(_sql.toString(),
    				ResultSet.TYPE_SCROLL_INSENSITIVE,
    				ResultSet.CONCUR_READ_ONLY);
    		_dirtyCount = 0;
    		ps.setString(++_dirtyCount, this.getID());
    		ps.setString(++_dirtyCount, this.getPath());
    		ps.setInt(++_dirtyCount, this.getIndex()==null?0:this.getIndex());
    		ps.setInt(++_dirtyCount, this.getModuleStatus()==null?0:getModuleStatus());
    		ps.setString(++_dirtyCount, this.getName());
    		ps.setString(++_dirtyCount, this.getModuleId());
    		ps.setString(++_dirtyCount, this.getPersonId());
    		
      		ps.setString(++_dirtyCount, this.getExprocession());
    		ps.setString(++_dirtyCount, this.getType());
    		ps.setString(++_dirtyCount, this.getWinConfig());
    		ps.setString(++_dirtyCount, this.getUrl());
    		ps.setString(++_dirtyCount, this.getChildModule());
    		ps.setString(++_dirtyCount, this.getCls());
    		ps.setString(++_dirtyCount, this.getIcon());
    		ps.setString(++_dirtyCount, this.getThumb());
    		ps.setTimestamp(++_dirtyCount,  new java.sql.Timestamp(this.getCreatTime().getTime()));
    		ps.setTimestamp(++_dirtyCount, 	new java.sql.Timestamp(this.getLastModified().getTime()));
    		ps.executeUpdate();
    		ps.close();
	}
    
	
	
	private String getString(ResultSet rs, Object column) {
		if (column != null && !column.toString().equals("")) {
			try {
				return rs.getString(((ColumnMapping) column).getColumnAlias());
			} catch (SQLException ex) {
				return null;
			}
		}
		return null;
	}

	private Date getDate(ResultSet rs, Object column) {
		if (column != null && !column.toString().equals("")) {
			try {
				return rs.getDate(((ColumnMapping) column).getColumnAlias());
			} catch (SQLException ex) {
				return null;
			}
		}
		return null;
	}
	
	private Integer getInt(ResultSet rs, Object column) {
		if (column != null && !column.toString().equals("")) {
			try {
				return rs.getInt(((ColumnMapping) column).getColumnAlias());
			} catch (SQLException ex) {
				return null;
			}
		}
		return 0;
	}
	public DbPersonModuleProperty clone() {
		DbPersonModuleProperty moduleProperty=new DbPersonModuleProperty(this.configCode);
		moduleProperty.setChildModule(childModule);
		moduleProperty.setID(ID);
		moduleProperty.setPath(path);
		moduleProperty.setIndex(index);
		moduleProperty.setName(name);
		moduleProperty.setModuleStatus(moduleStatus);
		moduleProperty.setModuleId(moduleId);
		moduleProperty.setExprocession(exprocession);
		moduleProperty.setPersonId(personId);
		moduleProperty.setUrl(url);
		moduleProperty.setType(type);
		moduleProperty.setWinConfig(winConfig);
		moduleProperty.setCls(cls);
		moduleProperty.setIcon(icon);
		moduleProperty.setThumb(thumb);
		moduleProperty.setCreatTime(creatTime);
		moduleProperty.setLastModified(lastModified);
		return moduleProperty;
	}

	public String getChildModule() {
		return childModule;
	}

	public void setChildModule(String childModule) {
		this.childModule = childModule;
	}



	public String getExprocession() {
		return exprocession;
	}

	public void setExprocession(String exprocession) {
		this.exprocession = exprocession;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getWinConfig() {
		return winConfig;
	}

	public void setWinConfig(String winConfig) {
		this.winConfig = winConfig;
	}

	public List<DbPersonModuleProperty> getChildModuleList() throws ModuleNotFoundException {
		if (childModuleList==null){
			childModuleList=new ArrayList();
			if (this.getChildModule()!=null && this.getChildModule().equals("")){
				String[] modules=this.getChildModule().split(",");
				for(int k=0;k<modules.length;k++){
					String moduleId=modules[k];
						childModuleList.add(AppCacheManager.getInstance(configCode).getPersonModulePropertyByID(moduleId, personId));
				}
			}
		}
		return childModuleList;
	}

	public void setChildModuleList(List<DbPersonModuleProperty> childModuleList) {
		this.childModuleList = childModuleList;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCls() {
		return cls;
	}

	public void setCls(String cls) {
		this.cls = cls;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public Integer getIndex() {
		return index;
	}

	public void setIndex(Integer index) {
		this.index = index;
	}

	public Integer getModuleStatus() {
		return moduleStatus;
	}

	public void setModuleStatus(Integer moduleStatus) {
		this.moduleStatus = moduleStatus;
	}

	public String getIcon() {
		return icon;
	}

	public void setIcon(String icon) {
		this.icon = icon;
	}

	public String getThumb() {
		return thumb;
	}

	public void setThumb(String thumb) {
		this.thumb = thumb;
	}

	public Date getCreatTime() {
		return creatTime;
	}

	public void setCreatTime(Date creatTime) {
		this.creatTime = creatTime;
	}

	public Date getLastModified() {
		return lastModified;
	}

	public void setLastModified(Date lastModified) {
		this.lastModified = lastModified;
	}


}
